package es.udc.emarketapp.http.controller.actions.products;

import es.udc.emarketapp.emarket.model.category.vo.CategoryVO;
import es.udc.emarketapp.emarket.model.categoryFacade.CategoryFacade;
import es.udc.emarketapp.emarket.model.product.vo.ProductVO;
import es.udc.emarketapp.emarket.model.productFacade.ProductFacade;
import es.udc.emarketapp.emarket.model.productFacade.vo.ProductChunkVO;
import es.udc.emarketapp.http.view.actionForms.FindProductsForm;
import es.udc.fbellas.j2ee.util.exceptions.InstanceNotFoundException;
import es.udc.fbellas.j2ee.util.exceptions.InternalErrorException;
import es.udc.fbellas.j2ee.util.struts.action.DefaultAction;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

public class FindProductsAction extends DefaultAction {

    public ActionForward doExecute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException, InternalErrorException {

        /* Get data. */
        FindProductsForm findProductsForm = (FindProductsForm) form;
        Long idCat = findProductsForm.getIdCat();
        String key = findProductsForm.getKey();


        /*********************************************/
        CategoryFacade categoryFacade = new CategoryFacade();

        CategoryVO categoryVO = null;
        ActionMessages errors = new ActionMessages();

        try {

            categoryVO = categoryFacade.findCategoryById(idCat);

        } catch (InstanceNotFoundException e) {

            errors.add("identifier",
                    new ActionMessage("ErrorMessages.category.notFound"));
            saveErrors(request, errors);
        }

        request.setAttribute("nomCat", categoryVO.getNomCat());
        request.setAttribute("idCat", idCat);

        /***********************************************/
        if (key.isEmpty()) {
            return mapping.findForward("noKeyWords");
        } else {
            if (FindProductsForm.ALL_CATEGORIES == idCat) {
                return doFindByKeywords(mapping, key,
                        findProductsForm.getStartIndex(),
                        findProductsForm.getCount(), request);
            } else {
                return doFindByKeywordsAndCategory(mapping, key, idCat,
                        findProductsForm.getStartIndex(),
                        findProductsForm.getCount(), request);
            }
        }
    }

    private ActionForward doFindByKeywords(ActionMapping mapping, String key,
            int startIndex, int count, HttpServletRequest request)
            throws InternalErrorException {

        /* Find products by key. */
        ProductFacade productFacade = new ProductFacade();
        ProductChunkVO productChunkVO = productFacade.findByKeywords(key, startIndex, count);


        if (productChunkVO.getProductVOs().size() > 0) {
            request.setAttribute("products",
                    productChunkVO.getProductVOs());
        }

        /* Generate parameters for previous and next links. */
        Map previousLinkParameters = getPreviousLinkParameters(key, null,
                startIndex, count);


        if (previousLinkParameters != null) {
            request.setAttribute("previous", previousLinkParameters);

        }

        if (productChunkVO.getExistMoreProducts()) {
            Map nextLinkParameters = getNextLinkParameters(key, null,
                    startIndex, count);
            request.setAttribute("next", nextLinkParameters);

        } /* Return ActionForward. */
        return mapping.findForward("success");


    }

    private ActionForward doFindByKeywordsAndCategory(ActionMapping mapping,
            String key, Long idCat, int startIndex, int count,
            HttpServletRequest request) throws InternalErrorException {

        /* Find products by Key and Category. */
        ProductFacade productFacade = new ProductFacade();
        ProductChunkVO productChunkVO = productFacade.findByKeywordsAndCategory(key, idCat, startIndex, count);


        if (productChunkVO.getProductVOs().size() > 0) {
            request.setAttribute("products", productChunkVO.getProductVOs());

        } /* Generate parameters for previous and next links. */
        Map previousLinkParameters = getPreviousLinkParameters(key, idCat,
                startIndex, count);


        if (previousLinkParameters != null) {
            request.setAttribute("previous", previousLinkParameters);

        }

        if (productChunkVO.getExistMoreProducts()) {
            Map nextLinkParameters = getNextLinkParameters(key, idCat,
                    startIndex, count);
            request.setAttribute("next", nextLinkParameters);


        } /* Return ActionForward. */
        return mapping.findForward("success");

    }

 
    private Map getPreviousLinkParameters(String key, Long idCat,
            int startIndex, int count) {

        Map linkAttributes = null;

        if ((startIndex - count) > 0) {

            linkAttributes = getCommonPreviousNextLinkParameters(key, idCat,
                    startIndex, count);
            linkAttributes.put("startIndex", new Integer(startIndex - count));

        }

        return linkAttributes;


    }

    private Map getNextLinkParameters(String key, Long idCat, int startIndex,
            int count) {

        Map linkAttributes = getCommonPreviousNextLinkParameters(key, idCat,
                startIndex, count);

        linkAttributes.put("startIndex", new Integer(startIndex + count));

        return linkAttributes;
    }

    private Map getCommonPreviousNextLinkParameters(String key, Long idCat,
            int startIndex, int count) {

        Map linkAttributes = new HashMap();

        linkAttributes.put("key", key);
        linkAttributes.put("idCat", idCat);
        linkAttributes.put("count", new Integer(count));

        return linkAttributes;

    }
}
